import React, { useState, useMemo, useEffect } from 'react';
import { ColView, filter_list, useHigh, GridTable, filter_row, useCmd, WaitUmd, MainView, no_del, trim_data, KFile, HandView, BtTxt,
    Title, obj_str_trim, to_float, KFind, useKForm, d_sort, cline, obj_str, PanelFind, Btn, is_empty, loc, uDb } from 'sui';
import { get_col, face_list, yn_list,st_list, load_tech, load_stuff, load_ng, fix_col, get_ck } from './cmd';
import { load_col, load_supply } from '../../stock/base/cmd';
import { useAccess } from 'cache';
import { Census } from './census';
import { NgView } from './ng';

const BaseView = ({ mod, submod, title, acc }) => {
    const [tech, setTech] = useState();
    const [supply, setSupply] = useState();
    const [stuff, setStuff] = useState();
    const [map_stuff, mapStuff] = useState();
    const [ng, setNg] = useState();
    const [map_ng, mapNg] = useState();
    const [map_supply, mapSupply] = useState();
    const [col, setCol] = useState();
    const [high] = useHigh(200, 100);
    const [no_acc] = useAccess();
    const umd = useCmd(`file/list/${mod}`);
    const form = useKForm();

    useEffect(() => {
        load_col(mod, setCol);
        load_supply(submod, setSupply, mapSupply);
        load_stuff(setStuff, mapStuff);
        load_ng(setNg, mapNg, mod);
        load_tech(setTech);
    }, [mod, submod]);

    const getRow = useMemo(() => {
        let data = umd.value;
        if (!data) {
            return null;
        }

        const opt_tech = obj_str_trim(form.value, "tech");
        const opt_ball = obj_str_trim(form.value, "ball");
        const opt_state = obj_str_trim(form.value, "state");

        data = data.filter(d => {
            if (opt_tech) {
                if (obj_str_trim(d, "tech") !== opt_tech) {
                    return false;
                }
            }

            if (opt_ball) {
                if (obj_str_trim(d, "ball") !== opt_ball) {
                    return false;
                }
            }

            if (opt_state) {
                if (obj_str_trim(d, "state") !== opt_state) {
                    return false;
                }
            }

            return true;
        });

        const lst = filter_list(["sn"], col);
        const ret = filter_row(data, lst, umd.filter);

        if (is_empty(ret)) {
            return ret;
        }

        d_sort(ret, "tech");
        ret.forEach((d, i) => d["posid"] = i);

        return ret;
    }, [umd.value, umd.filter, col, form.value]);

    const techList = useMemo(() => {
        const data = umd.value;

        if (is_empty(data)) {
            return null;
        }

        const set = new Set();
        const ret = [];

        data.forEach(d => {
            const tech = obj_str_trim(d, "tech");
            if (set.has(tech)) {
                return;
            }

            ret.push({ sn: "" + tech, name: tech });
            set.add(tech);
        });

        d_sort(ret, "sn");

        return ret;
    }, [umd.value]);

    const ballList = useMemo(() => {
        const data = umd.value;

        if (is_empty(data)) {
            return null;
        }

        const set = new Set();
        const ret = [];

        data.forEach(d => {
            const ball = to_float(obj_str_trim(d, "ball"));
            if (set.has(ball)) {
                return;
            }

            ret.push({ sn: "" + ball, name: ball });
            set.add(ball);
        });

        d_sort(ret, "sn");

        return ret;
    }, [umd.value]);

    const hreturn = () => {
        load_col(mod, setCol);
        umd.hreturn();
    };

    const act = {
        "add": (v, h) => {
            umd.startWait();

            uDb(null, "code/gen",
                {
                    line: cline(),
                    rule: submod,
                },
                r => {
                    form.clear_all();

                    const sn = obj_str(r, "psn");
                    v["sn"] = sn;

                    umd.update(`file/md/${mod}`, {v: v, sn: sn}, h);
                },
                e => umd.setErr(loc("l_755")));
        },
        "edit": (v, h) => umd.update(`file/md/${mod}`, {v: v, sn: v["sn"]}, h),
    };

    if (umd.isFin("col")) {
        const list = [
            {sn: mod, name: title, fix: fix_col()},
        ];

        return <ColView hreturn={hreturn} title={title} subtitle={loc("l_221")} list={list} cur={mod}/>;
    } else if (umd.isFin("census")) {
        return <Census data={tech} hreturn={() => umd.hreturn()} title={title} mod={submod} col={col}
        map_ng={map_ng} map_stuff={map_stuff} map_supply={map_supply}/>;
    } else if (umd.isFin("ng")) {
        return <NgView data={tech} hreturn={() => umd.hreturn()} title={title} mod={submod} col={col}
        map_ng={map_ng} map_stuff={map_stuff} map_supply={map_supply}/>;
    }

    const hDel = (d) => {
        const order = obj_str(d, "order");
        if (order) {
            alert(loc("l_104"));
            return;
        }

        if (no_del()) {
            return;
        }

        umd.update(`file/rm/${mod}`, {"sn": obj_str(d, "sn")});
    };

    const hCol = () => {
        if (is_empty(col)) {
            return null;
        }

        const ret = [];

        col.forEach(d => {
            if (d.sn === "sn") {
                d.ctp = "auto";
            } else if (d.sn === "supply") {
                d.ctp = "list";
                d.ctl = supply;
            } else if (d.sn === "tech") {
                d.ctp = "list";
                d.ctl = tech;
            } else if (d.sn === "face") {
                d.ctp = "list";
                d.ctl = face_list();
            } else if (d.sn === "state") {
                d.ctp = "list";
                d.ctl = st_list();
            } else if (d.sn === "stuff") {
                d.ctp = "list";
                d.ctl = stuff;
            } else if (d.sn === "yn") {
                d.ctp = "list";
                d.ctl = yn_list();
            } else if (d.sn === "ngson") {
                d.ctp = "list";
                d.ctl = ng;
            }

            ret.push(d);
        });

        return ret;
    };

    if (umd.isFin("edit") || umd.isFin("add")) {
        return <HandView umd={umd} title={title} act={act} col={hCol()} ck={get_ck(umd.cur, umd.value, col)}/>;
    }

    const hImport = (val) => {
        if (is_empty(col)) {
            alert(loc("l_686"));
            return;
        }

        if (is_empty(val)) {
            alert(loc("l_276"));
            return;
        }

        trim_data(val, ["sn"]);

        umd.update(`file/modify/${mod}`, {v: val});
    };

    const getCol = () => {
        if (is_empty(col)) {
            return null;
        }

        const tmp = [
            {name: loc("l_193"), key: 'index', width: 70, frozen: true},
            {name: loc("l_238"), key: 'e_opt', width: 126, frozen: true, formatter: props => {
                const d = props.row;
                return (
                    <div className="inline-flex">
                        <BtTxt hcmd={() => umd.pact(null, d, "edit")} disabled={no_acc(acc)}>{loc("l_235")}</BtTxt>
                        <BtTxt hcmd={() => hDel(d)} disabled={no_acc(acc)}>{loc("l_237")}</BtTxt>
                    </div>
                );
            }},
        ];

        get_col(col, tmp, map_supply, map_stuff, map_ng);

        return tmp;
    };

    const getList = () => {
        if (is_empty(col)) {
            return null;
        }

        return col.map(d => d.sn);
    };

    const rowTempl = () => {
        const tmp = getList();
        if (is_empty(tmp)) {
            return null;
        }

        const v = {};
        tmp.forEach(k => v[k] = "1");

        return [v];
    };

    const Right = () => (
        <div className="inline-flex">
            <Btn className="mr-4" hcmd={() => umd.pact(null, null, "col")} disabled={no_acc(acc)}>{loc("l_221")}</Btn>
            <KFile umd={umd} title={title} col={getList()} row={rowTempl()} hcmd={hImport} no_acc_in={no_acc(acc)}/>
            <Btn color="green" hcmd={() => umd.pact(null, null, "add")} className="ml-3" disabled={no_acc(acc)}>{loc("l_239")}</Btn>
        </div>
    );

    const Left = () => {
        const hsyn = () => {
            umd.startWait();
            umd.reload(() => {
                umd.endWait();
                alert(loc("l_789"));
            });
        };

        return (
            <div className="inline-flex items-center">
                <Title mod={title} sub={loc("l_769")}/>
                <Btn className="ml-8 mr-4" color="teal" hcmd={hsyn}>{loc("l_790")}</Btn>
                <Btn hcmd={() => umd.pact(null, null, "census")} color="teal">{loc("l_793")}</Btn>
                <Btn className="ml-4" hcmd={() => umd.pact(null, null, "ng")} color="teal">{loc("l_813")}</Btn>
            </div>
        );
    };

    return (
        <MainView>
            <PanelFind left={<Left/>} right={<Right/>} hcmd={umd.setFilter}>
                <div className="inline-flex items-center">
                    <KFind label={loc("l_363")} form={form} name="tech" margin="dense" width="w-56" list={techList}/>
                    <KFind label={loc("l_714")} form={form} name="ball" margin="dense" width="w-56" list={ballList} className="ml-4"/>
                    <KFind label={loc("l_131")} form={form} name="state" margin="dense" width="w-56" list={st_list()} className="ml-4"/>
                    <Btn className="ml-4" hcmd={() => form.clear_all()}>{loc("l_543")}</Btn>
                </div>
            </PanelFind>
            <GridTable col={getCol()} row={getRow} high={high}/>
            <WaitUmd umd={umd}/>
        </MainView>
    );
};

export {BaseView};
